#include "SBaseDialog.h"

#include <QEvent>
#include <QLabel>
#include <QMouseEvent>
#include <QStylePainter>
#include <QVBoxLayout>

#include "SImageButton.h"
#include "WidgetResizer.h"

#pragma region TitleBar

DlgTitleBar::DlgTitleBar(SBaseDialog* parent) : QWidget(parent), m_dlg(parent) {
  setMouseTracking(true);
  setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Fixed);
  setFixedHeight(29);

  QHBoxLayout* titleLayout = new QHBoxLayout();
  titleLayout->setSpacing(0);
  titleLayout->setContentsMargins(0, 0, 0, 0);

  m_titleLabel = new QLabel(this);
  m_titleLabel->setAlignment(Qt::AlignCenter);
  titleLayout->addWidget(m_titleLabel);

  titleLayout->addStretch();

  m_btnReload = new SImageButton(this, "widgets_action_refresh");
  m_btnPin = new SImageButton(this, "widgets_win_pin");
  m_btnPinSel = new SImageButton(this, "widgets_win_pin_selected");
  m_btnFull = new SImageButton(this, "widgets_win_full");
  m_btnRestore = new SImageButton(this, "widgets_win_restore");
  m_btnClose = new SImageButton(this, "widgets_win_close");

  titleLayout->addWidget(m_btnReload);
  titleLayout->addWidget(m_btnPin);
  titleLayout->addWidget(m_btnPinSel);
  titleLayout->addWidget(m_btnFull);
  titleLayout->addWidget(m_btnRestore);
  titleLayout->addWidget(m_btnClose);

  dlgTypeChanged();

  setLayout(titleLayout);

  connect(m_btnClose, &SImageButton::clicked, m_dlg, &SBaseDialog::reject);
  connect(m_btnReload, &SImageButton::clicked, this,
          &DlgTitleBar::onBtnClicked);
  connect(m_btnPin, &SImageButton::clicked, this, &DlgTitleBar::onBtnClicked);
  connect(m_btnPinSel, &SImageButton::clicked, this,
          &DlgTitleBar::onBtnClicked);
  connect(m_btnFull, &SImageButton::clicked, this, &DlgTitleBar::onBtnClicked);
  connect(m_btnRestore, &SImageButton::clicked, this,
          &DlgTitleBar::onBtnClicked);
  connect(this, &QWidget::windowTitleChanged, this, &DlgTitleBar::setTitle);
}

void DlgTitleBar::dlgTypeChanged() {
  bool isDlg = m_dlg->m_winType == SBaseDialog::WindowType::kDialog;
  bool isFixedDlg = m_dlg->m_winType == SBaseDialog::WindowType::kFixedDialog;
  bool isChildWindow = m_dlg->m_winType == SBaseDialog::WindowType::kChild;

  m_btnReload->setVisible(m_webDlg);
  m_btnPin->setVisible(
      isDlg && !m_dlg->windowFlags().testFlag(Qt::WindowStaysOnTopHint));
  m_btnPinSel->setVisible(
      isDlg && m_dlg->windowFlags().testFlag(Qt::WindowStaysOnTopHint));
  m_btnFull->setVisible(isDlg && !m_dlg->isMaximized());
  m_btnRestore->setVisible(isDlg && m_dlg->isMaximized());
  m_btnClose->setVisible(isDlg || isFixedDlg);
}

void DlgTitleBar::setTitle(const QString& title) {
  m_titleLabel->setText(title);
}

void DlgTitleBar::setWebDlg(bool v) {
  m_webDlg = v;
  m_btnReload->setVisible(m_webDlg);
}

void DlgTitleBar::onBtnClicked() {
  if (sender() == m_btnPin) {
    m_btnPin->setVisible(false);
    m_btnPinSel->setVisible(true);
    m_dlg->setWindowFlag(Qt::WindowStaysOnTopHint);
    m_dlg->show();
  } else if (sender() == m_btnPinSel) {
    m_btnPin->setVisible(true);
    m_btnPinSel->setVisible(false);
    m_dlg->setWindowFlag(Qt::WindowStaysOnTopHint, false);
    m_dlg->show();
  } else if (sender() == m_btnFull) {
    m_btnFull->setVisible(false);
    m_btnRestore->setVisible(true);
    m_dlg->showMaximized();
  } else if (sender() == m_btnRestore) {
    m_btnFull->setVisible(true);
    m_btnRestore->setVisible(false);
    m_dlg->showNormal();
  }
}

void DlgTitleBar::mousePressEvent(QMouseEvent* e) {
  m_dragPos = e->globalPos();
}

void DlgTitleBar::mouseMoveEvent(QMouseEvent* e) {
  QPoint offset = e->globalPos() - m_dragPos;
  if (e->buttons().testFlag(Qt::LeftButton) && offset.manhattanLength() >= 5) {
    m_dlg->move(m_dlg->pos() + offset);
    m_dragPos = e->globalPos();
    m_dlg->moving(m_dlg);
  }

  return QWidget::mouseMoveEvent(e);
}

void DlgTitleBar::mouseDoubleClickEvent(QMouseEvent* event) {
  m_btnFull->setVisible(m_dlg->isMaximized());
  m_btnRestore->setVisible(!m_dlg->isMaximized());

  if (m_dlg->isMaximized())
    m_dlg->showNormal();
  else
    m_dlg->showMaximized();
}

#pragma endregion

SBaseDialog::SBaseDialog(WindowType type, QWidget* parent) : QFrame(parent) {
  setWindowFlag(Qt::FramelessWindowHint);
  setStyleSheet("SBaseDialog {border: 1px solid #12696B;\nborder-radius:2px}");

  QVBoxLayout* layout = new QVBoxLayout(this);
  layout->setContentsMargins(2, 0, 2, 2);
  m_titleBar = new DlgTitleBar(this);
  layout->addWidget(m_titleBar);
  setLayout(layout);

  m_resizer = new WidgetResizer(this);
  setWindowType(type);
}

SBaseDialog::~SBaseDialog() {}

void SBaseDialog::paintEvent(QPaintEvent* event) {
  if (m_winType != WindowType::kChild) {
    QColor c(isActiveWindow() ? 0x12696B : 0x193D37);
    QStylePainter painter(this);
    QRect r(rect().topLeft(), QSize(rect().width(), 30));
    painter.fillRect(r, c);
  }
}

void SBaseDialog::showEvent(QShowEvent* event) {
  static bool s_initialized = false;
  if (!s_initialized) {
    if (sizePolicy() == QSizePolicy(QSizePolicy::Fixed, QSizePolicy::Fixed)) {
    }

    s_initialized = true;
  }
  QFrame::showEvent(event);
}

void SBaseDialog::doModal() {
  setWindowModality(Qt::WindowModality::ApplicationModal);
  show();
}

void SBaseDialog::setWindowType(WindowType type) {
  if (m_winType != type) {
    m_winType = type;
    if (type == WindowType::kDialog || type == WindowType::kFixedDialog) {
      if (m_titleBar) m_titleBar->show();
    }

    else {
      if (m_titleBar) m_titleBar->hide();
    }

    if (m_titleBar) m_titleBar->dlgTypeChanged();

    m_resizer->enable(m_winType == WindowType::kDialog);
    show();
  }
}

void SBaseDialog::setTitle(const QString& title) {
  m_titleBar->setTitle(title);
}

void SBaseDialog::setContentWidget(QWidget* w, bool web) {
  m_webContent = web;
  if (m_contentWidget != nullptr) layout()->removeWidget(m_contentWidget);

  resize(w->width() + 5, w->height() + 33);
  layout()->addWidget(w);
  w->setMouseTracking(true);
  m_contentWidget = w;
}

void SBaseDialog::removeContentWidget() {
  layout()->removeWidget(m_contentWidget);
  m_contentWidget = nullptr;
}

void SBaseDialog::detach() {
  setParent(nullptr);
  setWindowType(WindowType::kDialog);
}

void SBaseDialog::done(QDialog::DialogCode code) {
  finished(code);
  if (code == QDialog::Accepted)
    accepted();
  else
    rejected();

  close();
}